<?php
/**
 * MYSQL连接池新增WEBSOCKET服务
 * TODO 创建连接MYSQL的服务地址 3310
 */
$MService = new \swoole_server('0.0.0.0', 3310);
$MService->set([
    'worker_num' => 1, // worker进程数量
    'task_worker_num' => 10 // task进程数量 即为维持的MySQL连接的数量
]);

/**
 * TODO 写文件内容
 * @param string $msg
 */
function queryLogger($msg)
{
    $filePath = dirname(__FILE__) . '/../Log/ws_querydb.log';
    if(!file_exists($filePath)){
        @file_put_contents($filePath,"NewFile! \n");
    }
    @file_put_contents($filePath, $msg, FILE_APPEND);
}

/**
 * TODO 接收数据
 *
 * @param object $serv
 * @param int $fd
 * @param int $from_id
 * @param array $data
 */
function onMysqlReceive($serv, $fd, $from_id, $data)
{
    // TODO taskwait就是投递一条任务，这里直接传递SQL语句
    queryLogger("接收指令：{$data} " . PHP_EOL);
    $result = $serv->taskwait($data); // 然后阻塞等待SQL完成，并返回结果
    queryLogger("指令结束：{$data} " . PHP_EOL);

    if ($result !== false) {
        // TODO 数据库操作成功了，执行业务逻辑代码，这里就自动释放掉MySQL连接的占用
        list ($status, $db_res) = explode(':', $result, 2);
        if ($status == 'OK') {
            $serv->send($fd, json_encode(unserialize($db_res)) . PHP_EOL); // 返回处理数据给客户端
        } else {
            $serv->send($fd, $db_res);
        }
        return;
    } else {
        $serv->send($fd, "Error. Task timeout\n"); // 如果返回的是false，则说明taskwait等待超时，可以设置相应的等待超时时间
    }
}

// 执行任务
function onMysqlTask($serv, $task_id, $from_id, $sql)
{
    static $link = null;
    $queryRes = FALSE;
    queryLogger("开始做任务：task id{$task_id} " . PHP_EOL);
    HELL:
    if ($link == null) {
        // 游戏配置：'HOST' => '192.168.0.147','USER' => 'root','PASSWORD' => 'svn678mysql', 'DB_NAME' => 'ChessCards',
        $link = @mysqli_connect("192.168.0.147", "root", "svn678mysql", "ChessCards");
        if (! $link) {
            $link = null;
            $serv->finish("ER:" . mysqli_error($link));
            return;
        }
    }
    $result = $link->query($sql);
    
    if (!$result) {    // 如果查询失败了
        $errorNos = [2006,  2013];
        if (in_array(mysqli_errno($link), $errorNos)) { // 错误码为2013，或者2006，则重连数据库，重新执行sql
            $link = null;
            goto HELL;
        } else {
            $serv->finish("ER:" . mysqli_error($link));
            return;
        }
    }
    if (preg_match("/^select/i", $sql)) { // 如果是select操作，就返回关联数组
        $queryRes = $result->fetch_assoc();
    } else {
        $queryRes = $result; // 否则直接返回结果
    }
    $serv->finish("OK:" . serialize($queryRes)); // 调用finish方法，用于在task进程中通知worker进程，投递的任务已完成
}

// 结束
function onMysqlFinish($serv, $task_id, $data)
{
    queryLogger("所有任务完成：task id {$task_id} Finish:Connect.PID=" . posix_getpid() . PHP_EOL); // taskwait 没有触发这个函数。。
}

// 启动Swoole服务
$MService->on('receive', 'onMysqlReceive');
$MService->on('task', 'onMysqlTask');
$MService->on('Finish', 'onMysqlFinish');
// 启动server
$MService->start();

?>